
package com.binance.autojob.utils;

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.reflect.FastClass;
import org.springframework.cglib.reflect.FastMethod;
import org.springframework.util.StringUtils;

import com.binance.autojob.annotation.MyScheduledJob;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.executor.XxlJobExecutor;
import com.xxl.job.core.handler.IJobHandler;

/**
 * 执行器扩展
 * 
 * @author zhangwenhui
 *
 */
public class ExecutorExt {


    private static Logger logger = LoggerFactory.getLogger(ExecutorExt.class);

    private static ConcurrentHashMap<String, MyScheduledJob> jobStore = new ConcurrentHashMap<>();
    
    
    static {
        try {
            new JobTimer(jobStore).start();//定时处理要注册的任务
        } catch (Exception e) {
            logger.error("",e);
        }
    }

    /**
     * 类方法注册
     * 
     * @param method
     * @param name
     */
    public static void regist(final Object serviceBean, final Method method, final MyScheduledJob scheduled) {
        String name = getJobName(method, scheduled);
        logger.info("拦截到的方法：{}，任务名:{}", method, name);
        if (XxlJobExecutor.loadJobHandler(name) == null) {

            IJobHandler handler = new IJobHandler() {

                @Override
                public ReturnT<String> execute(String param) throws Exception {
                    try {
                        /** 执行被拦截的方法 */
                        Class<?> serviceClass = serviceBean.getClass();
                        String methodName = method.getName();
                        Class<?>[] parameterTypes = method.getParameterTypes();
                        Object[] parameters = method.getParameters();
                        FastClass serviceFastClass = FastClass.create(serviceClass);
                        FastMethod serviceFastMethod = serviceFastClass.getMethod(methodName, parameterTypes);
                        if (parameterTypes != null && parameterTypes.length == 1
                                && parameterTypes[0].isAssignableFrom(String.class)) {// 处理参数
                            serviceFastMethod.invoke(serviceBean, new Object[] {param});
                        } else {

                            serviceFastMethod.invoke(serviceBean, parameters);
                        }
                        // 此处或许需要返回值?
                        return ReturnT.SUCCESS;
                    } catch (Throwable e) {
                        logger.error("任务调用执行异常，MethodName is [" + method + "]", e);
                        return new ReturnT<String>(ReturnT.FAIL_CODE,e.getMessage());
                    }
                }
            };
            XxlJobExecutor.registJobHandler(name, handler);
            // 异步注册任务
            jobStore.put(name, scheduled);
            logger.info("Registed jobs :{}", jobStore.size());
        } else {
            logger.debug("Registed Method【{}】 has registed !", name);
        }
    }



    private static String getJobName(final Method method, final MyScheduledJob scheduled) {
        String value = scheduled.value();
        if (method.getAnnotation(MyScheduledJob.class) == null) {
            // 注解在类上
            String prix = StringUtils.isEmpty(value) ? "" : value + "_";
            return prix + method.getDeclaringClass().getName() + "." + method.getName();
        } else {
            // 在方法上
            return StringUtils.isEmpty(value) ? method.getDeclaringClass().getName() + "." + method.getName() : value;
        }
    }
}
